﻿using System;

namespace SkeinLibManaged
{       
    public static partial class ThreeFish
    {
        #region "Core Utilities Specific for 1024"
        private static void MIX1K(UInt64[] buf,
                            byte X1, byte Y1, RC1K N1,
                            byte X2, byte Y2, RC1K N2,
                            byte X3, byte Y3, RC1K N3,
                            byte X4, byte Y4, RC1K N4,
                            byte X5, byte Y5, RC1K N5,
                            byte X6, byte Y6, RC1K N6,
                            byte X7, byte Y7, RC1K N7,
                            byte X8, byte Y8, RC1K N8)
        {   buf[X1] += buf[Y1];  ROTL64(ref (buf[Y1]), (byte)(N1));  buf[Y1] ^= buf[X1];
            buf[X2] += buf[Y2];  ROTL64(ref (buf[Y2]), (byte)(N2));  buf[Y2] ^= buf[X2];
            buf[X3] += buf[Y3];  ROTL64(ref (buf[Y3]), (byte)(N3));  buf[Y3] ^= buf[X3];
            buf[X4] += buf[Y4];  ROTL64(ref (buf[Y4]), (byte)(N4));  buf[Y4] ^= buf[X4];
            buf[X5] += buf[Y5];  ROTL64(ref (buf[Y5]), (byte)(N5));  buf[Y5] ^= buf[X5];
            buf[X6] += buf[Y6];  ROTL64(ref (buf[Y6]), (byte)(N6));  buf[Y6] ^= buf[X6];
            buf[X7] += buf[Y7];  ROTL64(ref (buf[Y7]), (byte)(N7));  buf[Y7] ^= buf[X7];
            buf[X8] += buf[Y8];  ROTL64(ref (buf[Y8]), (byte)(N8));  buf[Y8] ^= buf[X8];
        }

        private static void INVMIX1K(UInt64[] buf,
                            byte X1, byte Y1, RC1K N1,
                            byte X2, byte Y2, RC1K N2,
                            byte X3, byte Y3, RC1K N3,
                            byte X4, byte Y4, RC1K N4,
                            byte X5, byte Y5, RC1K N5,
                            byte X6, byte Y6, RC1K N6,
                            byte X7, byte Y7, RC1K N7,
                            byte X8, byte Y8, RC1K N8)
        {   buf[Y1] ^= buf[X1];  ROTR64(ref (buf[Y1]), (byte)(N1));  buf[X1] -= buf[Y1];
            buf[Y2] ^= buf[X2];  ROTR64(ref (buf[Y2]), (byte)(N2));  buf[X2] -= buf[Y2];
            buf[Y3] ^= buf[X3];  ROTR64(ref (buf[Y3]), (byte)(N3));  buf[X3] -= buf[Y3];
            buf[Y4] ^= buf[X4];  ROTR64(ref (buf[Y4]), (byte)(N4));  buf[X4] -= buf[Y4];
            buf[Y5] ^= buf[X5];  ROTR64(ref (buf[Y5]), (byte)(N5));  buf[X5] -= buf[Y5];
            buf[Y6] ^= buf[X6];  ROTR64(ref (buf[Y6]), (byte)(N6));  buf[X6] -= buf[Y6];
            buf[Y7] ^= buf[X7];  ROTR64(ref (buf[Y7]), (byte)(N7));  buf[X7] -= buf[Y7];
            buf[Y8] ^= buf[X8];  ROTR64(ref (buf[Y8]), (byte)(N8));  buf[X8] -= buf[Y8];
        }

        private static void KEYI1K(UInt64[] k, UInt64[] t, System.Byte round, UInt64[] b)
        {   b[0] += k[(round + 0) % 17];
            b[1] += k[(round + 1) % 17];
            b[2] += k[(round + 2) % 17];
            b[3] += k[(round + 3) % 17];
            b[4] += k[(round + 4) % 17];
            b[5] += k[(round + 5) % 17];
            b[6] += k[(round + 6) % 17];
            b[7] += k[(round + 7) % 17];
            b[8] += k[(round + 8) % 17];
            b[9] += k[(round + 9) % 17];
            b[10] += k[(round + 10) % 17];
            b[11] += k[(round + 11) % 17];
            b[12] += k[(round + 12) % 17];
            b[13] += k[(round + 13) % 17] + t[(round + 0) % 3];
            b[14] += k[(round + 14) % 17] + t[(round + 1) % 3];
            b[15] += k[(round + 15) % 17] + round;
        }

        private static void INVKEYI1K(UInt64[] k, UInt64[] t, System.Byte round, UInt64[] b)
        {   b[0] -= (k[(round + 0) % 17]);
            b[1] -= (k[(round + 1) % 17]);
            b[2] -= (k[(round + 2) % 17]);
            b[3] -= (k[(round + 3) % 17]);
            b[4] -= (k[(round + 4) % 17]);
            b[5] -= (k[(round + 5) % 17]);
            b[6] -= (k[(round + 6) % 17]);
            b[7] -= (k[(round + 7) % 17]);
            b[8] -= (k[(round + 8) % 17]);
            b[9] -= (k[(round + 9) % 17]);
            b[10] -= (k[(round + 10) % 17]);
            b[11] -= (k[(round + 11) % 17]);
            b[12] -= (k[(round + 12) % 17]);
            b[13] -= (k[(round + 13) % 17] + t[(round + 0) % 3]);
            b[14] -= (k[(round + 14) % 17] + t[(round + 1) % 3]);
            b[15] -= (k[(round + 15) % 17] + round);
        }
        #endregion

        /// <summary>
        /// Transform sixteen 64-bit words according to ThreeFish algorithm.
        /// </summary>
        /// <param name="input">The words to be transformed.</param>
        /// <param name="key">The sixteen 64-bit key words used during the transformation.</param>
        /// <param name="tweak">The two 64-bit tweak words used in conjunction with the key.</param>
        /// <param name="feed">False for encryption, true for hashing mechanism used by Skein.</param>
        /// <returns>Array of sixteen 64-bit tranformed words.</returns>
        public static UInt64[] ThreeFish1024Words(
                    UInt64[] input, UInt64[] key, UInt64[] tweak, System.Boolean feed)
        {
            //Error checking!
            if (input == null)
                throw new System.ArgumentNullException("ThreeFish1024Words: Input cannot be null!");
            if (key == null)
                throw new System.ArgumentNullException("ThreeFish1024Words: Key cannot be null!");
            if (tweak == null)
                throw new System.ArgumentNullException("ThreeFish1024Words: Tweak cannot be null!");
            if (input.Length != 16)
                throw new System.ArgumentException("ThreeFish1024Words: Incorrect length for input word array.");
            if (key.Length != 16)
                throw new System.ArgumentException("ThreeFish1024Words: Incorrect length for key word array.");
            if (tweak.Length != 2)
                throw new System.ArgumentException("ThreeFish1024Words: Incorrect length for tweak word array.");
            UInt64[] buf = { input[0], input[1], input[2], input[3],
                             input[4], input[5], input[6], input[7],
                             input[8], input[9], input[10], input[11],
                             input[12], input[13], input[14], input[15] };
            UInt64[] locKey = { key[0], key[1], key[2], key[3],
                                key[4], key[5], key[6], key[7],
                                key[8], key[9], key[10], key[11],
                                key[12], key[13], key[14], key[15],
                                UNIQUE_K(key) };
            UInt64[] locTweak = {tweak[0], tweak[1], (tweak[0] ^ tweak[1])};
            UInt64[] locFeed = null;
            if (feed == true)
            {
                locFeed = new UInt64[] { input[0], input[1], input[2], input[3], input[4], input[5], input[6], input[7], 
                                         input[8], input[9], input[10], input[11], input[12], input[13], input[14], input[15] };
            };
            
            KEYI1K(locKey, locTweak, 0, buf);
            MIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            MIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            MIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            MIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            KEYI1K(locKey, locTweak, 1, buf);
            MIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            MIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            MIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            MIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            KEYI1K(locKey, locTweak, 2, buf);
            MIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            MIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            MIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            MIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            KEYI1K(locKey, locTweak, 3, buf);
            MIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            MIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            MIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            MIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            KEYI1K(locKey, locTweak, 4, buf);
            MIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            MIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            MIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            MIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            KEYI1K(locKey, locTweak, 5, buf);
            MIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            MIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            MIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            MIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            KEYI1K(locKey, locTweak, 6, buf);
            MIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            MIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            MIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            MIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            KEYI1K(locKey, locTweak, 7, buf);
            MIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            MIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            MIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            MIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            KEYI1K(locKey, locTweak, 8, buf);
            MIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            MIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            MIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            MIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            KEYI1K(locKey, locTweak, 9, buf);
            MIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            MIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            MIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            MIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            KEYI1K(locKey, locTweak, 10, buf);
            MIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            MIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            MIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            MIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            KEYI1K(locKey, locTweak, 11, buf);
            MIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            MIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            MIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            MIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            KEYI1K(locKey, locTweak, 12, buf);
            MIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            MIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            MIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            MIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            KEYI1K(locKey, locTweak, 13, buf);
            MIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            MIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            MIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            MIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            KEYI1K(locKey, locTweak, 14, buf);
            MIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            MIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            MIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            MIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            KEYI1K(locKey, locTweak, 15, buf);
            MIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            MIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            MIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            MIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            KEYI1K(locKey, locTweak, 16, buf);
            MIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            MIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            MIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            MIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            KEYI1K(locKey, locTweak, 17, buf);
            MIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            MIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            MIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            MIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            KEYI1K(locKey, locTweak, 18, buf);
            MIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            MIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            MIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            MIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            KEYI1K(locKey, locTweak, 19, buf);
            MIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            MIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            MIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            MIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            KEYI1K(locKey, locTweak, 20, buf);
         
	        for (byte i = 0; i < 16; i++)
            {   if (feed == true) buf[i] ^= locFeed[i];
            }
            return buf;
        }

        /// <summary>
        /// If the ThreeFish1024Words transformation was done with "feed" = false, the words can be "untransformed" with the
        /// SAME key AND tweak using this function.
        /// </summary>
        /// <param name="input">The sixteen 64-bit key words to be recovered.</param>
        /// <param name="key">The sixteen 64-bit key words used during the transformation.</param>
        /// <param name="tweak">The two 64-bit tweak words used in conjunction with the key.</param>
        /// <returns>Array of sixteen 64-bit untranformed words.</returns>
        public static UInt64[] InvThreeFish1024Words(
                    UInt64[] input, UInt64[] key, UInt64[] tweak)
        {
            //Error checking!
            if (input == null)
                throw new System.ArgumentNullException("InvThreeFish1024Words: Input cannot be null!");
            if (key == null)
                throw new System.ArgumentNullException("InvThreeFish1024Words: Key cannot be null!");
            if (tweak == null)
                throw new System.ArgumentNullException("InvThreeFish1024Words: Tweak cannot be null!");
            if (input.Length != 16)
                throw new System.ArgumentException("InvThreeFish1024Words: Incorrect length for input word array.");
            if (key.Length != 16)
                throw new System.ArgumentException("InvThreeFish1024Words: Incorrect length for key word array.");
            if (tweak.Length != 2)
                throw new System.ArgumentException("InvThreeFish1024Words: Incorrect length for tweak word array.");
            UInt64[] buf = { input[0], input[1], input[2], input[3],
                             input[4], input[5], input[6], input[7],
                             input[8], input[9], input[10], input[11],
                             input[12], input[13], input[14], input[15] };
            UInt64[] locKey = { key[0], key[1], key[2], key[3],
                                key[4], key[5], key[6], key[7],
                                key[8], key[9], key[10], key[11],
                                key[12], key[13], key[14], key[15],
                                UNIQUE_K(key) };
            UInt64[] locTweak = { tweak[0], tweak[1], (tweak[0] ^ tweak[1]) };

            INVKEYI1K(locKey, locTweak, 20, buf);
            INVMIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            INVMIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            INVMIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            INVMIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            INVKEYI1K(locKey, locTweak, 19, buf);
            INVMIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            INVMIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            INVMIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            INVMIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            INVKEYI1K(locKey, locTweak, 18, buf);
            INVMIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            INVMIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            INVMIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            INVMIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            INVKEYI1K(locKey, locTweak, 17, buf);
            INVMIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            INVMIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            INVMIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            INVMIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            INVKEYI1K(locKey, locTweak, 16, buf);
            INVMIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            INVMIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            INVMIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            INVMIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            INVKEYI1K(locKey, locTweak, 15, buf);
            INVMIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            INVMIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            INVMIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            INVMIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            INVKEYI1K(locKey, locTweak, 14, buf);
            INVMIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            INVMIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            INVMIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            INVMIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            INVKEYI1K(locKey, locTweak, 13, buf);
            INVMIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            INVMIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            INVMIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            INVMIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            INVKEYI1K(locKey, locTweak, 12, buf);
            INVMIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            INVMIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            INVMIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            INVMIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            INVKEYI1K(locKey, locTweak, 11, buf);
            INVMIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            INVMIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            INVMIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            INVMIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            INVKEYI1K(locKey, locTweak, 10, buf);
            INVMIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            INVMIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            INVMIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            INVMIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            INVKEYI1K(locKey, locTweak, 9, buf);
            INVMIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            INVMIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            INVMIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            INVMIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            INVKEYI1K(locKey, locTweak, 8, buf);
            INVMIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            INVMIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            INVMIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            INVMIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            INVKEYI1K(locKey, locTweak, 7, buf);
            INVMIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            INVMIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            INVMIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            INVMIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            INVKEYI1K(locKey, locTweak, 6, buf);
            INVMIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            INVMIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            INVMIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            INVMIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            INVKEYI1K(locKey, locTweak, 5, buf);
            INVMIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            INVMIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            INVMIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            INVMIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            INVKEYI1K(locKey, locTweak, 4, buf);
            INVMIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            INVMIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            INVMIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            INVMIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            INVKEYI1K(locKey, locTweak, 3, buf);
            INVMIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            INVMIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            INVMIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            INVMIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            INVKEYI1K(locKey, locTweak, 2, buf);
            INVMIX1K(buf, 0, 15, RC1K.R7A, 2, 11, RC1K.R7B, 6, 13, RC1K.R7C, 4, 9, RC1K.R7D, 14, 1, RC1K.R7E, 8, 5, RC1K.R7F, 10, 3, RC1K.R7G, 12, 7, RC1K.R7H);
            INVMIX1K(buf, 0, 7, RC1K.R6A, 2, 5, RC1K.R6B, 4, 3, RC1K.R6C, 6, 1, RC1K.R6D, 12, 15, RC1K.R6E, 14, 13, RC1K.R6F, 8, 11, RC1K.R6G, 10, 9, RC1K.R6H);
            INVMIX1K(buf, 0, 9, RC1K.R5A, 2, 13, RC1K.R5B, 6, 11, RC1K.R5C, 4, 15, RC1K.R5D, 10, 7, RC1K.R5E, 12, 3, RC1K.R5F, 14, 5, RC1K.R5G, 8, 1, RC1K.R5H);
            INVMIX1K(buf, 0, 1, RC1K.R4A, 2, 3, RC1K.R4B, 4, 5, RC1K.R4C, 6, 7, RC1K.R4D, 8, 9, RC1K.R4E, 10, 11, RC1K.R4F, 12, 13, RC1K.R4G, 14, 15, RC1K.R4H);
            INVKEYI1K(locKey, locTweak, 1, buf);
            INVMIX1K(buf, 0, 15, RC1K.R3A, 2, 11, RC1K.R3B, 6, 13, RC1K.R3C, 4, 9, RC1K.R3D, 14, 1, RC1K.R3E, 8, 5, RC1K.R3F, 10, 3, RC1K.R3G, 12, 7, RC1K.R3H);
            INVMIX1K(buf, 0, 7, RC1K.R2A, 2, 5, RC1K.R2B, 4, 3, RC1K.R2C, 6, 1, RC1K.R2D, 12, 15, RC1K.R2E, 14, 13, RC1K.R2F, 8, 11, RC1K.R2G, 10, 9, RC1K.R2H);
            INVMIX1K(buf, 0, 9, RC1K.R1A, 2, 13, RC1K.R1B, 6, 11, RC1K.R1C, 4, 15, RC1K.R1D, 10, 7, RC1K.R1E, 12, 3, RC1K.R1F, 14, 5, RC1K.R1G, 8, 1, RC1K.R1H);
            INVMIX1K(buf, 0, 1, RC1K.R0A, 2, 3, RC1K.R0B, 4, 5, RC1K.R0C, 6, 7, RC1K.R0D, 8, 9, RC1K.R0E, 10, 11, RC1K.R0F, 12, 13, RC1K.R0G, 14, 15, RC1K.R0H);
            INVKEYI1K(locKey, locTweak, 0, buf);

            return buf;
        }
    }
}
